package com.github.shuaidd.rest.runtime;

import com.github.shuaidd.model.execption.NotFoundException;
import com.github.shuaidd.model.execption.NotPermittedException;
import com.github.shuaidd.service.runtime.LwfCommentService;
import com.github.shuaidd.service.runtime.LwfPermissionService;
import org.activiti.app.domain.runtime.Comment;
import org.activiti.app.model.common.ResultListDataRepresentation;
import org.activiti.app.model.runtime.CommentRepresentation;
import org.activiti.app.security.SecurityUtils;
import org.activiti.app.service.exception.BadRequestException;
import org.activiti.engine.HistoryService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.identity.User;
import org.apache.commons.lang3.StringUtils;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;

public class AbstractCommentsResource {

    @Inject
    private LwfPermissionService permissionService;

    @Inject
    private LwfCommentService commentService;

    @Inject
    private HistoryService historyService;

    public ResultListDataRepresentation getTaskComments(String taskId, Boolean latestFirst) {

        User currentUser = SecurityUtils.getCurrentUserObject();
        checkReadPermissionOnTask(currentUser, taskId);
        List<Comment> comments = commentService.getCommentsForTask(taskId, Boolean.TRUE.equals(latestFirst));

        // Create representation for all comments
        List<CommentRepresentation> commentList = new ArrayList<CommentRepresentation>();
        for (Comment comment : comments) {
            commentList.add(new CommentRepresentation(comment));
        }

        return new ResultListDataRepresentation(commentList);
    }

    public CommentRepresentation addTaskComment(CommentRepresentation commentRequest, String taskId) {

        if (StringUtils.isBlank(commentRequest.getMessage())) {
            throw new BadRequestException("Comment should not be empty");
        }

        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new NotFoundException("No task found with id: " + taskId);
        }

        // Check read permission and message
        User currentUser = SecurityUtils.getCurrentUserObject();
        checkReadPermissionOnTask(currentUser, taskId);

        // Create comment
        Comment comment = commentService.createComment(commentRequest.getMessage(), currentUser, task.getId(), task.getProcessInstanceId());
        return new CommentRepresentation(comment);
    }

    public ResultListDataRepresentation getProcessInstanceComments(String processInstanceId, Boolean latestFirst) {

        User currentUser = SecurityUtils.getCurrentUserObject();
        checkReadPermissionOnProcessInstance(currentUser, processInstanceId);
        List<Comment> comments = commentService.getCommentsForProcessInstance(processInstanceId, Boolean.TRUE.equals(latestFirst));

        // Create representation for all comments
        List<CommentRepresentation> commentList = new ArrayList<CommentRepresentation>();
        for (Comment comment : comments) {
            commentList.add(new CommentRepresentation(comment));
        }

        return new ResultListDataRepresentation(commentList);
    }

    public CommentRepresentation addProcessInstanceComment(CommentRepresentation commentRequest, String processInstanceId) {

        if (StringUtils.isBlank(commentRequest.getMessage())) {
            throw new BadRequestException("Comment should not be empty");
        }

        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance == null) {
            throw new NotFoundException("No process instance found with id: " + processInstanceId);
        }

        // Check read permission and message
        User currentUser = SecurityUtils.getCurrentUserObject();
        checkReadPermissionOnProcessInstance(currentUser, processInstanceId);

        // Create comment
        Comment comment = commentService.createComment(commentRequest.getMessage(), currentUser, processInstanceId);
        return new CommentRepresentation(comment);
    }

    protected void checkReadPermissionOnTask(User user, String taskId) {
        if (taskId == null) {
            throw new BadRequestException("Task id is required");
        }
        permissionService.validateReadPermissionOnTask(SecurityUtils.getCurrentUserObject(), taskId);
    }

    protected void checkReadPermissionOnProcessInstance(User user, String processInstanceId) {
        if (processInstanceId == null) {
            throw new BadRequestException("Process instance id is required");
        }
        if (!permissionService.hasReadPermissionOnProcessInstance(SecurityUtils.getCurrentUserObject(), processInstanceId)) {
            throw new NotPermittedException("You are not permitted to read process instance with id: " + processInstanceId);
        }
    }
}
